using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using Styx;
using Styx.Helpers;
using Styx.Logic;
using Styx.Logic.Combat;
using Styx.Logic.Pathing;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;

using Natfoth.Helpers;
using Styx.WoWInternals.World;
using TreeSharp;
using Action = TreeSharp.Action;

namespace Natfoth.Classes
{
    public class Shaman
    {
        private static LocalPlayer Me { get { return ObjectManager.Me; } }
        private static WoWUnit Targ { get { return ObjectManager.Me.CurrentTarget; } }
        public static string Version = "0.0.1";
        public static string Name = "Akatosh Shaman";

        public static Composite ShamanRestBehavior()
        {
            return new PrioritySelector(   

                    
                    Lib.RestBehaviour()

                    
            );
        }

        public static Composite ShamanElementalCombat()
        {

            return new PrioritySelector(

                    new Lib.NeedToRetarget(new Lib.Retarget()),

                    new Lib.NeedToLOSCheck(new Lib.LOSCheck()),

                    new Lib.NeedToAutoAttack(new Lib.AutoAttack()),

                    new Decorator(akatosh => Targ == null,
                        new Action(akatosh => RunStatus.Success)),

                    new Decorator(akatosh => Targ != null && !Me.IsFacing(Targ),
                        new Action(akatosh => Lib.FaceTarget())),

					new Decorator(akatosh => Targ != null && Targ.Distance < 35 && Me.IsMoving,
						new Action(akatosh => Navigator.PlayerMover.MoveStop())),

					new Decorator(akatosh => Me.IsCasting && Me.CastingSpell.Name == "Flash Heal" && Me.HealthPercent > 95,
						new Action(akatosh => Spell.StopCasting())),

                        //Spells Here

                        Lib.Cast("Wind Shear", akatosh => Targ.IsCasting),
                       
						Lib.BuffSelf("Elemental Mastery", akatosh => Targ.IsPlayer),
                        
						Lib.Cast("Thunderstorm", akatosh => Targ.IsPlayer && Targ.Distance < 10 /*&& Me.ManaPercent > 50*/),
                        
						Lib.Cast("Unleashed Elements"),
                        
						Lib.Cast("Flame Shock", akatosh =>Targ.GetAuraTimeLeft("Flame Shock", true).Seconds < 3 || (!Targ.HasAura("Flame Shock"))),
                        
						Lib.Cast("Fire Nova", akatosh => Utils.CountOfAddsInRange(10, Targ.Location) > 2  && Targ.HasAura("Flame Shock")),
						   
                        
						Lib.Cast("Earth Shock", akatosh => Me.HasAura("Lightning Shield", 7)),
                        
						Lib.Cast("Lava Burst", akatosh => Lib.DebuffTimeRemining("Flame Shock") - (WoWSpell.FromId(8050).CastTime/1000) >= 0.25),
                        
						Lib.Cast("Chain Lightning", akatosh => Utils.CountOfAddsInRange(10, Targ.Location) > 2),
                        
						Lib.Cast("Lightning Bolt"),
                        
						Lib.Cast("Thunderstorm"),



                        //End Spells



                        

                    Lib.CreateMoveToTargetBehavior(true, Lib.LowestLevelRangeSpell().MaxRange-5),

                    new Action(ret => ObjectManager.Update())
             );
        }

        public static Composite ShamanEnhancmentCombat()
        {

            return new PrioritySelector(

                    new Lib.NeedToRetarget(new Lib.Retarget()),

                    //new Lib.NeedToCheckCombatTimer(new Lib.CheckCombatTimer()),

                    new Lib.NeedToLOSCheck(new Lib.LOSCheck()),

                    new Lib.NeedToAutoAttack(new Lib.AutoAttack()),

                    new Decorator(akatosh => Targ == null,
                        new Action(akatosh => RunStatus.Success)),

                    new Decorator(akatosh => Targ != null && !Me.IsFacing(Targ),
                        new Action(akatosh => Lib.FaceTarget())),

					new Decorator(akatosh => Targ != null && Targ.Distance < 35 && Me.IsMoving,
						new Action(akatosh => Navigator.PlayerMover.MoveStop())),

					new Decorator(akatosh => Me.IsCasting && Me.CastingSpell.Name == "Flash Heal" && Me.HealthPercent > 95,
						new Action(akatosh => Spell.StopCasting())),    

                        //Spells Here

						Lib.Cast("Wind Shear", akatosh => Targ.IsCasting),
                        
						
						Lib.Cast("Flame Shock", akatosh =>Targ.GetAuraTimeLeft("Flame Shock", true).Seconds < 3 || (!Targ.HasAura("Flame Shock"))),
						
                        
						//AOE items
						Lib.Cast("Chain Lightning", akatosh => Utils.CountOfAddsInRange(10, Targ.Location) > 2 && Me.HasAura("Maelstrom Weapon", 5)),
						
						Lib.Cast("Fire Nova", akatosh => Utils.CountOfAddsInRange(10, Targ.Location) > 2 && Targ.HasAura("Flame Shock")),
						
						//end AOE Items
                        
						
						
						Lib.Cast("Stormstrike"),
						
						Lib.Cast("Lava Lash"),
						
						Lib.Cast("Lightning Bolt", akatosh => Me.HasAura("Maelstrom Weapon", 5)),
						
						Lib.Cast("Primal Strike"),
						
						Lib.Cast("Unleash Elements"),
                        
						Lib.Cast("Earth Shock"),
						


                        //End Spells


						Lib.CreateMoveToMeleeBehavior(true),


                    

                    new Action(ret => ObjectManager.Update())
             );
        }

        public static Composite ShamanElementalCombatBuffs()
        {
            return new PrioritySelector(

                  Lib.Cast("Lightning Shield",
                       ret => !Me.HasAura("Lightning Shield", 3))
            );
        }

        public static bool ShamanElementalNeedBuffs()
        {
            /*if (!Lib.HasBuff("Inner Fire"))
                return true;

            if (!Lib.HasBuff("Power Word: Fortitude"))
                return true;*/

            return false;
        }

        public static Composite ShamanElementalBuffs()
        {
             return new PrioritySelector(

                  Lib.Cast("Lightning Shield",
                       ret => !Me.HasAura("Lightning Shield", 3)),
				 
					new Decorator(
					ret => !Lib.HasWeaponImbue(WoWInventorySlot.MainHand, "Flametongue") &&
                           Me.Inventory.Equipped.MainHand.TemporaryEnchantment.Id != 0,
                    new Action(
                        ret => Lua.DoString("CancelItemTempEnchantment(1)"))),
   
				Lib.Cast("Flametongue Weapon", ret => !Lib.HasWeaponImbue(WoWInventorySlot.MainHand, "Flametongue"))
            );
        }

        public static Composite ShamanEnhancmentCombatBuffs()
        {
            return new PrioritySelector(

                  Lib.Cast("Lightning Shield",
                       ret => !Me.HasAura("Lightning Shield", 3))
            );
        }
		
		public static Composite ShamanEnhancmentBuffs()
        {
            return new PrioritySelector(
			Lib.Cast("Lightning Shield",
                       ret => !Me.HasAura("Lightning Shield", 3)),

                //Removes the weapon enchant if the Imbue is the wrong one and then attempts to rebuff
                //MainHand
                new Decorator(
                    ret => !Lib.HasWeaponImbue(WoWInventorySlot.MainHand, "Windfury") &&
                           Me.Inventory.Equipped.MainHand.TemporaryEnchantment.Id != 0,
                    new Action(
                        ret => Lua.DoString("CancelItemTempEnchantment(1)"))),

					Lib.Cast("Windfury Weapon", ret => !Lib.HasWeaponImbue(WoWInventorySlot.MainHand, "Windfury")),

                // Low level support if there is no Windfury weapon yet...
                Lib.Cast("Flametongue Weapon", ret => !Lib.HasWeaponImbue(WoWInventorySlot.MainHand, "Windfury")),

                // Ignore off-hand if its not a weapon.
                new Decorator(
                    ret => Me.Inventory.Equipped.OffHand.ItemInfo.ItemClass == WoWItemClass.Weapon,
                    new PrioritySelector(
						//Offhand
                        new Decorator(
                            ret => !Lib.HasWeaponImbue(WoWInventorySlot.OffHand, "Flametongue") &&
                                   Me.Inventory.Equipped.OffHand != null &&
                                   Me.Inventory.Equipped.OffHand.TemporaryEnchantment.Id != 0,
                            new Action(
                                ret => Lua.DoString("CancelItemTempEnchantment(2)"))),

                        Lib.Cast("Flametongue Weapon", ret => !Lib.HasWeaponImbue(WoWInventorySlot.OffHand, "Flametongue"))
                        ))
            );
        }

        

        public static bool ShamanEnhancmentNeedBuffs()
        {
            /*if (!Lib.HasBuff("Inner Fire"))
                return true;

            if (!Lib.HasBuff("Power Word: Fortitude"))
                return true;*/

            return false;
        }

        

        public static Composite ShamanElementalPullBehavior()
        {
            return new PrioritySelector(

			   new Lib.NeedToNavigatePath(new Lib.NavigatePath()),

				new Decorator(akatosh => Me.Combat,
							  new Action(akatosh => RunStatus.Success)),


				new Lib.NeedToLOSCheck(new Lib.LOSCheck()),

				new Decorator(akatosh => Targ != null && !Me.IsFacing(Targ),
							  new Action(akatosh => Lib.FaceTarget())),

				new Decorator(akatosh => Targ != null && Targ.Distance < 35 && Me.IsMoving,
						new Action(akatosh => Navigator.PlayerMover.MoveStop())),

				new Lib.NeedToAutoAttack(new Lib.AutoAttack()),


               //Pull Spells


			   Lib.Cast("Lightning Bolt"),


               //End Pull Spells

				Lib.CreateMoveToTargetBehavior(true, Lib.LowestLevelRangeSpell().MaxRange-5),

				

                new Action(ret => ObjectManager.Update())
            );
        }

        public static Composite ShamanEnhancmentPullBehavior()
        {
            return new PrioritySelector(

                new Lib.NeedToNavigatePath(new Lib.NavigatePath()),

                //new Lib.NeedToBlacklistPullTarget(new Lib.BlacklistPullTarget()),

                //new Lib.NeedToCheckPullTimer(new Lib.BlacklistPullTarget()),
				new Decorator(akatosh => Targ == null,
						new Action(akatosh => RunStatus.Success)),

                new Lib.NeedToLOSCheck(new Lib.LOSCheck()),

                new Decorator(akatosh => Targ != null && !Me.IsFacing(Targ),
                    new Action(akatosh => Lib.FaceTarget())),

                new Lib.NeedToAutoAttack(new Lib.AutoAttack()),

                

               //Pull Spells





               //End Pull Spells



                Lib.CreateMoveToMeleeBehavior(true),



                new Action(ret => ObjectManager.Update())
            );
        }




        public static void ShamanEnchancmentClassPulse()
        {
            //int lootableMobs = LootTargeting.Instance.LootingList.Count;

            // If ShamanSettings.DirtyData = true it will reload the settings from the XML file
            // This reads the XML file and re-populates the ShamanSettings class with any changed values
            if (!AkatoshCore.Instance._isCCLoaded) { AkatoshCore.Instance._isCCLoaded = true; ShamanSettings.DirtyData = true; }
            if (ShamanSettings.DirtyData) AkatoshCore.Instance.LoadSettings(true);

            // So we don't overload HB the below code is only run once per second
            if (!Timers.Expired("Pulse", 1000)) return;
            Timers.Recycle("Pulse", 1000);

            // Environmental ShamanSettings
            if (Timers.Expired("EnvironmentSettings", 5000))
            {
                if (ShamanSettings.MultipleEnvironment.Contains("never"))
                {
                    ConfigSettings.CurrentEnvironment = "PVE";
                }
                else
                {
                    Timers.Reset("EnvironmentSettings");
                    string environment = Utils.IsBattleground ? "PVP" : "PVE";
                    environment = ObjectManager.Me.IsInInstance ? "Instance" : environment;
                    if (!ConfigSettings.UIActive && environment != ConfigSettings.CurrentEnvironment)
                    {
                        ConfigSettings.CurrentEnvironment = environment;
                        Utils.Log(string.Format("*** Environment has changed. Loading {0} settings.", environment), Utils.Colour("Red"));
                        AkatoshCore.Instance.LoadSettings(false);
                    }
                }
            }

           
        }
  
        



        public static void ShamanElementalClassPulse()
        {
            //int lootableMobs = LootTargeting.Instance.LootingList.Count;

            // If ShamanSettings.DirtyData = true it will reload the settings from the XML file
            // This reads the XML file and re-populates the ShamanSettings class with any changed values
            if (!AkatoshCore.Instance._isCCLoaded) { AkatoshCore.Instance._isCCLoaded = true; ShamanSettings.DirtyData = true; }
            if (ShamanSettings.DirtyData) AkatoshCore.Instance.LoadSettings(true);

            // So we don't overload HB the below code is only run once per second
            if (!Timers.Expired("Pulse", 1000)) return;
            Timers.Recycle("Pulse", 1000);

            // Environmental ShamanSettings
            if (Timers.Expired("EnvironmentSettings", 5000))
            {
                if (ShamanSettings.MultipleEnvironment.Contains("never"))
                {
                    ConfigSettings.CurrentEnvironment = "PVE";
                }
                else
                {
                    Timers.Reset("EnvironmentSettings");
                    string environment = Utils.IsBattleground ? "PVP" : "PVE";
                    environment = ObjectManager.Me.IsInInstance ? "Instance" : environment;
                    if (!ConfigSettings.UIActive && environment != ConfigSettings.CurrentEnvironment)
                    {
                        ConfigSettings.CurrentEnvironment = environment;
                        Utils.Log(string.Format("*** Environment has changed. Loading {0} settings.", environment), Utils.Colour("Red"));
                        AkatoshCore.Instance.LoadSettings(false);
                    }
                }
            }

           
        }
    }
}